package com.mallcloud.mall.product.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mallcloud.mall.common.core.constant.CacheConstants;
import com.mallcloud.mall.common.core.exception.ErrorCodes;
import com.mallcloud.mall.common.core.exception.FailException;
import com.mallcloud.mall.common.core.util.MsgUtils;
import com.mallcloud.mall.mall.api.entity.MallProductCategoryModel;
import com.mallcloud.mall.product.api.entity.CategoryModel;
import com.mallcloud.mall.product.mapper.CategoryMapper;
import com.mallcloud.mall.product.service.CategoryService;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 分类信息
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, CategoryModel> implements CategoryService {

    @Override
    @Cacheable(value = CacheConstants.PROJECT_CATEGORY_DETAILS, key = "#name",  unless = "#result.isEmpty()")
    public List<Tree<Long>> selectTree(Long parentId, String name) {
        // 查询全部分类
        List<CategoryModel> proCategoryList = this.list(
                Wrappers.<CategoryModel>lambdaQuery()
                        .like(StrUtil.isNotBlank(name), CategoryModel::getName, name)
                        .orderByAsc(CategoryModel::getSortOrder)
        );
        if(proCategoryList.isEmpty()){
            return Collections.emptyList();
        }
        List<TreeNode<Long>> collect = proCategoryList.stream()
                .sorted(Comparator.comparingInt(CategoryModel::getSortOrder))
                .map(getNodeFunction()).collect(Collectors.toList());

        // 模糊查询 不组装树结构 直接返回 表格方便编辑
        if (StrUtil.isNotBlank(name)) {
            return collect.stream().map(node -> {
                        Tree<Long> tree = new Tree<>();
                        tree.putAll(node.getExtra());
                        BeanUtils.copyProperties(node, tree);
                        return tree;
                    }
            ).collect(Collectors.toList());
        }
        return TreeUtil.build(collect, 0L);
}

    @Override
    @CacheEvict(value = {CacheConstants.PROJECT_CATEGORY_DETAILS,
                         CacheConstants.PROJECT_CATEGORY_TREE,
                         CacheConstants.PROJECT_CATEGORY_FIRST,
                         CacheConstants.PROJECT_CATEGORY_THIRD}, allEntries = true)
    public Boolean removeCategoryById(Long categoryId) {
        // 查询父节点为当前节点的节点
        long count = this.count(Wrappers.<CategoryModel>query().lambda().eq(CategoryModel::getParentId, categoryId));
        if (count > 0) {
            throw new FailException(MsgUtils.getMessage(ErrorCodes.SYS_CATEGORY_DELETE_EXISTING));
        }

        return this.removeById(categoryId);
    }

    @Override
    @CacheEvict(value = {CacheConstants.PROJECT_CATEGORY_DETAILS,
                         CacheConstants.PROJECT_CATEGORY_TREE,
                         CacheConstants.PROJECT_CATEGORY_FIRST,
                         CacheConstants.PROJECT_CATEGORY_THIRD}, allEntries = true)
    public Boolean updateCategoryById(CategoryModel dto) {
        return this.updateById(dto);
    }

    @Override
    @CacheEvict(value = {CacheConstants.PROJECT_CATEGORY_DETAILS,
                         CacheConstants.PROJECT_CATEGORY_TREE,
                         CacheConstants.PROJECT_CATEGORY_FIRST,
                         CacheConstants.PROJECT_CATEGORY_THIRD}, allEntries = true)
    public Boolean saveCategory(CategoryModel dto) {
        this.save(dto);
        if(dto.getParentId().equals(0L)){
            dto.setPath(String.valueOf(dto.getCategoryId()));
        }else{
            CategoryModel parent = this.getById(dto.getParentId());
            dto.setPath(parent.getPath().concat(String.format("-%s", dto.getCategoryId())));
        }
        this.updateById(dto);
        return Boolean.TRUE;
    }

    @NotNull
    private Function<CategoryModel, TreeNode<Long>> getNodeFunction() {
        return proCategory -> {
            TreeNode<Long> node = new TreeNode<>();
            node.setId(proCategory.getCategoryId());
            node.setName(proCategory.getName());
            node.setParentId(proCategory.getParentId());
            node.setWeight(proCategory.getSortOrder());
            // 扩展属性
            Map<String, Object> extra = new HashMap<>();
            if (StrUtil.isNotBlank(proCategory.getIcon())) {
                extra.put("icon", proCategory.getIcon());
            }
            if (StrUtil.isNotBlank(proCategory.getImgUrl())) {
                extra.put("imgUrl", proCategory.getImgUrl());
            }
            extra.put("status", proCategory.getStatus());
            extra.put("label", proCategory.getName());
            extra.put("shopId", proCategory.getShopId());
            extra.put("categoryLevel", proCategory.getCategoryLevel());
            extra.put("sortOrder", proCategory.getSortOrder());
            node.setExtra(extra);
            return node;
        };
    }
}
